package com.zcs.app.base.mvvm

import android.app.Dialog
import android.content.Intent
import android.os.Bundle
import android.text.TextUtils
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.databinding.ViewDataBinding
import androidx.fragment.app.Fragment
import androidx.lifecycle.LiveData
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
import com.tbruyelle.rxpermissions2.RxPermissions
import com.zcs.app.base.R
import com.zcs.app.base.asm.ActivityStackManger
import com.zcs.app.base.dialog.CustomDialogHelper
import com.zcs.app.base.utils.KLogUtil
import com.zcs.app.base.utils.ToastUtils
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.greenrobot.eventbus.EventBus
import java.lang.reflect.Method
import java.lang.reflect.ParameterizedType
import java.lang.reflect.Type

/**
 * Created by ZengCS on 2021/08/24.
 * BaseNormalKtFragmentAdv
 */
abstract class BaseKtFragment<T : ViewDataBinding, V : BaseViewModel> : Fragment() {
    protected val TAG: String = this.javaClass.simpleName

    // 这里保证不会在多线程调用rxPermissions，所以取消同步锁，减少消耗
    val rxPermissions by lazy(LazyThreadSafetyMode.NONE) {
        RxPermissions(this)
    }
    protected var isLoading = false
    private var progressDialog: Dialog? = null
    protected var mAppName: String? = null
    protected var isGoToAppSettings = false
    open fun needViewModel(): Boolean = true
    lateinit var binding: T
    lateinit var viewModel: V

    open fun isLazyInit(): Boolean = false

    fun attachBinding(t: T) {
        binding = t
        binding.lifecycleOwner = this
    }

    /**
     * 使用与父类相同的ViewModel，实现Fragment和Activity数据共享,默认false<br></br>
     *
     * **Note：当该方法返回true时，泛型VM必须与Activity使用同一个ViewModel**
     * @return boolean
     *  * false：不共享数据
     *  * true：需要通过ViewModel实现Fragment和Activity数据共享
     */
    open fun useSameViewModelOfActivity(): Boolean {
        return false
    }

    /**
     * 采用ViewPager + Fragment(FragmentStatePagerAdapter)时，需要实现该接口
     *
     * @return
     */
    val fragmentIdentifier: Int
        get() = 0

    val isFinishing: Boolean
        get() = activity == null || requireActivity().isFinishing

    override fun onDestroy() {
        hideLoading()
        progressDialog = null
        super.onDestroy()
        if (useEventBus()) //如果要使用eventbus请将此方法返回true
            EventBus.getDefault().unregister(this)
    }

    /**
     * 是否使用eventBus,默认为使用(true)，
     *
     * @return
     */
    open fun useEventBus(): Boolean {
        return false
    }

    abstract fun initData()

    abstract fun onInit()

    abstract fun initObserve()

    abstract fun initView()

    open fun addOnClickListener() {}

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        //使用了eventbus并且未注册时
        if (useEventBus() && !EventBus.getDefault().isRegistered(this)) //如果要使用eventbus请将此方法返回true
            EventBus.getDefault().register(this) //注册到事件主线

        //初始化ViewModel
        initViewModel()

    }

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        //反射方式
        initViewDataBinding()
        if (binding != null) {
            return binding.root
        }
        return super.onCreateView(inflater, container, savedInstanceState)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        mAppName = getString(R.string.app_name)
        registerBaseObserver()

        if (isLazyInit()) {
            lifecycleScope.launch {
                delay(500)
                withContext(Dispatchers.Main) {
                    if (!isFinishing) {
                        onInit()
                        addOnClickListener()
                        hideLoading()
                    }
                }
            }
        } else {
            onInit()
            addOnClickListener()
        }
    }

    /**
     * 根据设置的类的泛型参数通过反射方式实例化ViewDataBinding对象
     */
    private fun initViewDataBinding() {
        val vbClass: Class<T> = getVMClass(this.javaClass, 0) as Class<T>
        try {
            val start = System.currentTimeMillis()
            val method: Method = vbClass.getMethod("inflate", LayoutInflater::class.java)
            binding = method.invoke(null, layoutInflater) as T
            println("-=---------> ${System.currentTimeMillis() - start}")
        } catch (ex: Exception) {
            KLogUtil.e(Log.getStackTraceString(ex))
        }
    }

    /**
     * 基本数据订阅
     *
     */
    private fun registerBaseObserver() {
        //订阅loading消息
        registerLiveDataObserve(viewModel.showLoadingObserver) {
            if (it != null && it.isNotEmpty()) {
                if (it == BaseViewModel.TAG_HIDE_LOADING) {
                    hideLoading()
                } else {
                    showLoading(it)
                }
            }
        }

        //订阅toast消息
        registerLiveDataObserve(viewModel.showToastObserver) {
            if (it != null && it.isNotEmpty()) {
                showToast(it)
            }
        }

        //订阅showMessage消息
        registerLiveDataObserve(viewModel.showMessageObserver) {
            if (it != null && it.isNotEmpty()) {
                showMessage(it)
            }
        }
    }

    /**
     * 给指定的LiveData添加一个订阅事件
     *
     * 注：这里的lifecycleOwner使用viewLifecycleOwner
     */
    protected fun <LV> registerLiveDataObserve(liveData: LiveData<LV>, ret: (it: LV) -> Unit) {
        liveData.observe(viewLifecycleOwner, {
            ret(it)
        })
    }


    /**
     * 实例化ViewModel
     */
    private fun initViewModel() {
        val vmClass: Class<V> = getVMClass(this.javaClass, 1) as Class<V>

        //检测是否设置了与Activity使用相同的ViewModel实现数据共享，则需要检查设置的ViewModel是否与Activity中设置的是否一致
        if (useSameViewModelOfActivity()) {
            val act = requireActivity()
            val vmAct: Class<V> = getVMClass(act.javaClass, 1) as Class<V>
            if (vmClass.name != vmAct.name) {
                throw RuntimeException("请与Activity设置的ViewModel泛型保持一致，即：" + vmAct.getName())
            }
        }
        val viewModelProvider =
            if (useSameViewModelOfActivity()) ViewModelProvider(requireActivity()) else ViewModelProvider(
                this
            )
        viewModel = viewModelProvider.get(vmClass)
    }

    /**
     * 获取对应class类设置的第1个泛型参数对应的Class
     * @param clazz
     * @param actualTypeIndex 泛型參數索引位置
     * @return
     */
    private fun getVMClass(clazz: Class<*>, actualTypeIndex: Int): Type {
        var superClazz = clazz.genericSuperclass
        if (superClazz !is ParameterizedType) {
            throw RuntimeException("请设置类泛型")
        }

        val parameterizedType = superClazz as ParameterizedType

        return parameterizedType.actualTypeArguments[actualTypeIndex]
    }


    fun showLoading() {
        showLoading("数据加载中...")
    }

    fun hideLoading() {
        isLoading = false
        if (progressDialog != null && progressDialog!!.isShowing) progressDialog!!.dismiss()
    }

    fun showMessage(message: String) {
        hideLoading()
        CustomDialogHelper.showCustomMessageDialog(requireActivity(), message)
    }

    fun launchActivity(intent: Intent) {
        startActivity(intent)
    }

    fun launchActivity(clz: Class<*>?) {
        launchActivity(Intent(requireActivity(), clz))
    }

    fun killMyself() {
        if (activity != null && !requireActivity().isFinishing) {
            ActivityStackManger.finishActivity(requireActivity())
            requireActivity().finish()
        }
    }

    fun showLoading(msg: String) {
        // 显示Loading框
        if (activity is BaseKtActivity<*, *>) {
            (activity as BaseKtActivity<*, *>).showLoading()
        }
    }

    fun showToast(message: String) {
        if (TextUtils.isEmpty(message)) return
        ToastUtils.showLong(message)
    }

    //显示错题提示信息
    protected fun showLoadErrorMsg(errorMsg: String) {
        if (TextUtils.isEmpty(errorMsg)) {
            showToast("数据加载失败")
        } else {
            showToast(errorMsg)
        }
    }

    /**
     * 获取字符串资源
     *
     * @param stringId
     * @return
     */
    protected fun getStringValue(stringId: Int, vararg params: Any?): String {
        return resources.getString(stringId, *params)
    }

    /**
     * 1.默认是退出APP
     * 2.默认自动重新检测
     */
    fun onNeverAsk(permissionName: String) {
        if (activity is BaseKtActivity<*, *>) {
            (activity as BaseKtActivity<*, *>).onNeverAsk(
                permissionName,
                withExit = false,
                autoCheckOnResume = false
            )
        }
    }

    /**
     * 获取字符串资源
     *
     * @param stringId
     * @return
     */
    protected fun getStringValue(stringId: Int): String {
        return resources.getString(stringId)
    }

    /**
     * fragment对用户是否可见
     */
    val isVisibleToUser: Boolean
        get() = isResumed && userVisibleHint
}